package com.loeng.framework.mq.redis.config;

import com.loeng.framework.mq.redis.core.RedisMQTemplate;
import com.loeng.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
import com.loeng.framework.redis.config.LoengRedisAutoConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.util.List;

/**
 *  Redis 消息队列 Consumer 配置类
 * @ EnableScheduling 启用定时任务，用于 RedisPendingMessageResendJob 重发消息
 *
 * @author loeng zhuo
 */
@Slf4j
@EnableScheduling
@AutoConfiguration(after = LoengRedisAutoConfiguration.class)
public class LoengRedisMQConsumerAutoConfiguration {

    /**
     * 创建 Redis Pub/Sub 广播消费的容器
     * ConditionalOnBean(AbstractRedisChannelMessageListener.class) 只有 AbstractChannelMessageListener 存在的时候，才需要注册 Redis pubsub 监听
     */
    @Bean
    @ConditionalOnBean(AbstractRedisChannelMessageListener.class)
    public RedisMessageListenerContainer redisMessageListenerContainer(
            RedisMQTemplate redisMQTemplate, List<AbstractRedisChannelMessageListener<?>> listeners) {
        // 创建 RedisMessageListenerContainer 对象
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        // 设置 RedisConnection 工厂。
        container.setConnectionFactory(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory());
        // 添加监听器
        listeners.forEach(listener -> {
            listener.setRedisMQTemplate(redisMQTemplate);
            container.addMessageListener(listener, new ChannelTopic(listener.getChannel()));
            log.info("[redisMessageListenerContainer][注册 Channel({}) 对应的监听器({})]",
                    listener.getChannel(), listener.getClass().getName());
        });
        return container;
    }

}
